package com.example.demo.controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;

// 让这个类可以被浏览器访问
@RequestMapping("/yesterday")
@RestController
public class HelloController {

    // 为这个方法配置对应的路径
    @RequestMapping("/sayhi")
    public String sayHi() {
        return "hi, SpringBoot";
    }

    @RequestMapping("/sayhello")
    public String sayHello() {
        return "hello, SpringBoot";
    }
}


@RequestMapping("/today")
@RestController
class TodaySpringWebMvc {

    // 传递单个或多个参数
    /**
     * 不加限制时，可以使用任意方式进行访问
     * 当不传递值时，默认为null，因为我们使用的是包装类
     * 若是使用基本类型，则会报错*/
    @RequestMapping("/m1")
    public String m1(String name, Integer age) {
        return "My name is " + name + ", I am " + age + " years old.";
    }

    // 指定请求方式
    /**
     * 限定访问方式为get
     * 使用其它方式访问会响应405错误状态码*/
    @RequestMapping(value = "/m2", method = RequestMethod.GET)
    public String m2(String message) {
        return "接收到参数为：" + message;
    }

    // 传递对象参数
    /**
     * 在客户端传递数据时，直接使用对象的属性名进行传递
     * Spring框架会将参数名与属性名一一映射并赋值*/
    @RequestMapping("/m3")
    public String m3(Person person) {
        return "接收到参数为：" + person.toString();
    }

    // 参数重命名
    /**
     * 当我们需要修改形参名时，可以使用@RequestParam注解进行操作
     * 注解内放入旧的形参名 外面跟上新的形参名
     * 其底层逻辑为：使用旧形参名进行接收，再赋值给新的形参
     * 注意事项：若是使用该注解，会默认将该参数设置为必传，我们可以通过required参数进行取消*/
    @RequestMapping("/m4")
    public String m4(@RequestParam(value = "name", required = false) String userName) {
        return "接收到参数：" + userName;
    }

    // 传递数组
    /**
     * 在请求中，若是一个参数有多个赋值，浏览器会帮我们将其封装为一个数组
     * 如 http://127.0.0.1:8080/today/m5?arr=1&arr=2&arr=3 */
    @RequestMapping("/m5")
    public String m5(String[] arr) {
        return "接收到参数：" + Arrays.toString(arr);
    }

    // 使用List接收数组参数
    @RequestMapping("/m6")
    public String m6(@RequestParam("arr") List<String> arr) {
        return "接收到参数：" + arr.toString();
    }

    // 传递json数据
    /**
     * 接收对象的结构与JSON数据结构需一致，并且不传也会赋值为null
     * 因此建议将对象中的属性使用包装类定义*/
    @RequestMapping("/m7")
    public String m7(@RequestBody Person student) {
        return "接收到对象参数：" + student.toString();
    }


    // 通过url路径传递参数
    @RequestMapping("/m8/{userId}/{userName}")
    public String m8(@PathVariable String userName, @PathVariable Integer userId) {
        return "接收到参数：userId=" + userId + ", userName=" + userName;
    }

    // 传递文件
    @RequestMapping("/m9")
    public String m9(@RequestPart MultipartFile file) throws IOException {
        // 打印文件名
        System.out.println(file.getOriginalFilename());
        // 将文件存储起来
        // 此处需要写绝对地址
        file.transferTo(new File("D:/" + file.getOriginalFilename()));
        // 返回操作结果
        return "success";
    }

    // 获取cookie
    /**
     * 使用servlet的方式获取cookie*/
    @RequestMapping("/getCookieByServlet")
    public String getCookieByServlet(HttpServletRequest request) {
        // 获取cookie列表
        Cookie[] cookies = request.getCookies();
        // 准备返回值
        String ret = "";
        if(cookies != null) {
            for(Cookie x: cookies) {
                ret += x.getName() + ":" + x.getValue() + "\n";
            }
        }
        return "接收到cookie：\n" + ret;
    }


    /**
     * 使用Spring注解的方式获取cookie*/
    @RequestMapping("/getCookieBySpring")
    public String getCookieBySpring(@CookieValue("addr") String addr) {
        return "获取到cookie中的addr：" + addr;
    }

    // 获取session
    /**
     * 使用Servlet的方式获取session*/
    @RequestMapping("/setSession")
    public String setSession(HttpServletRequest request) {
        // getSession()方法需要传递一个Boolean类型的参数，用于指定当session不存在时是否创建
        // 默认为 true
        HttpSession session = request.getSession();
        // 新增session值
        session.setAttribute("username", "careathers");
        session.setAttribute("uesrid", "2325253435");
        return "新增session值";
    }

    @RequestMapping("/getSessionByServlet")
    public String getSessionByServlet(HttpServletRequest request) {
        // 获取session，若是没有不创建
        HttpSession session = request.getSession(false);
        // 获取session值
        String s = "";
        if(session != null) {
            Enumeration<String> sessionNames = session.getAttributeNames();
            while(sessionNames.hasMoreElements()) {
                String name = sessionNames.nextElement();
                s += name + ":" + session.getAttribute(name) + "\n";
            }
        }
        return "获取到session：" + s;
    }

    /**
     * 使用 @SessionAttribute 注解获取 session属性*/
    @RequestMapping("/getSessionBySpring")
    public String getSessionBySpring(@SessionAttribute("username") String userName) {
        return "获取到session属性值：" + userName;
    }

    /**
     * 使用 HttpSession内置对象进行获取*/
    @RequestMapping("/getSessionByObject")
    public String getSessionByObject(HttpSession session) {
        return "获取session属性值：" + session.getAttribute("username");
    }

    // 获取Headers
    /**
     * 使用这个键盘打字 感觉还行 不是很迟钝，就是键位布置有点奇怪
     * 使用Servlet的方式进行获取*/
    @RequestMapping("/getHeaderByServlet")
    public String getHeaderByServlet(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        return "用户标志：" + userAgent;
    }

    /**
     * 使用 @RequestHeader 注解进行获取*/
    @RequestMapping("/getHeaderBySpring")
    public String getHeaderBySpring(@RequestHeader("User-Agent") String userAgent) {
        return "用户标志：" + userAgent;
    }

    /**
     * 使用Java Spring Web 框架展示计算结果*/
    @RequestMapping("/acount")
    public Integer test1() {
        return 'a' - 'a';
    }
}

